package com.hhh.springai_test.controller;


import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hhh.springai_test.common.BaseResponse;
import com.hhh.springai_test.common.ErrorCode;
import com.hhh.springai_test.common.ResultUtils;
import com.hhh.springai_test.config.AppConfig;
import com.hhh.springai_test.constant.CodeConstant;
import com.hhh.springai_test.constant.UserConstant;
import com.hhh.springai_test.exception.BusinessException;
import com.hhh.springai_test.mapper.UserMapper;
import com.hhh.springai_test.model.dto.user.*;
import com.hhh.springai_test.model.po.User;
import com.hhh.springai_test.model.vo.ListUserCountVo;
import com.hhh.springai_test.model.vo.UserInfoAdminVO;
import com.hhh.springai_test.model.vo.UserVo;
import com.hhh.springai_test.service.UserService;
import com.hhh.springai_test.utils.NetUtils;
import com.hhh.springai_test.utils.RedisUtils;
import com.hhh.springai_test.utils.StringUtils;
import com.hhh.springai_test.utils.VerifyCodeUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;



@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private AppConfig appConfig;

    @Resource
    private JavaMailSender javaMailSender;

    @Resource
    private UserMapper userMapper;

    /**
     * 获取验证码接口
     * 该方法用于生成并返回一个验证码图片和对应的唯一标识符
     * 验证码用于用户验证，以确保用户是真人而非自动化程序
     *
     * @param response HttpServletResponse对象，用于向客户端返回数据
     * @param request HttpServletRequest对象，用于获取客户端请求信息
     * @return BaseResponse<Map<String, String>> 包含验证码信息的响应对象
     */
    @GetMapping("/checkCode")
    public BaseResponse<Map<String, String>> getCheckCode(HttpServletResponse response, HttpServletRequest request) {
        // 获取请求者的IP地址
        String ipAddress = NetUtils.getIpAddress(request);
        System.out.println("ipAddress = " + ipAddress);

        // 使用提取的函数处理 Redis 尝试次数
        handleRedisAttemptCount(CodeConstant.REDIS_LOCK_KEY + ipAddress,CodeConstant.REDIS_LOCK_TIMEOUT,3);

        // 生成4位随机验证码
        String code = VerifyCodeUtils.generateVerifyCode(4);
        // 生成一个唯一标识符
        String uuid = UUID.randomUUID().toString();
        // 将验证码和唯一标识符组合后保存到Redis中，并设置过期时间为60秒
        redisUtils.setex(CodeConstant.CHECK_CODE_KEY + uuid, code, 60);

        // 创建一个输出流，用于存储生成的验证码图片
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            // 根据指定的宽度、高度、存储流和验证码内容生成验证码图片
            VerifyCodeUtils.outputImage(130, 60, baos, code);
        } catch (IOException e) {
            log.error("生成随机验证码失败: {}", e);
            throw new BusinessException(407, "验证码生成失败");
        }

        // 将生成的验证码图片转换为Base64格式字符串
        String base64Image = Base64.getEncoder().encodeToString(baos.toByteArray());

        // 创建返回的Map对象，将uuid和base64编码的图片字符串放入其中
        Map<String, String> responseMap = new HashMap<>();
        responseMap.put("uuid", uuid);
        responseMap.put("image", "data:image/png;base64," + base64Image);

        // 最后，构建并返回一个包含成功状态码和Map数据的响应对象
        return ResultUtils.success(responseMap);
    }

    /**
     * 验证验证码的正确性
     *
     * @param checkCodeDto 包含验证码和UUID的对象
     * @return 验证结果，true表示验证码正确
     * @throws BusinessException 如果验证码或UUID为空，或验证码不正确，则抛出业务异常
     */
    @PostMapping("/verificationCode")
    public BaseResponse<Boolean> checkCode(@RequestBody CheckCodeDto checkCodeDto){
        // 获取用户输入的验证码和UUID
        String code = checkCodeDto.getCode();
        String uuid = checkCodeDto.getUuid();

        // 检查 uuid 是否为空
        if(StrUtil.isEmpty(uuid)){
            throw new BusinessException(405,"uuid不能为空");
        }
        // 检查验证码是否为空
        if(StrUtil.isEmpty(code)){
            throw new BusinessException(405,"验证码不能为空");
        }
        // 查找验证码
        Object cachedCode = redisUtils.get(CodeConstant.CHECK_CODE_KEY + uuid);
        // 如果找不到对应的验证码，抛出异常
        if (cachedCode == null) {
            throw new BusinessException(406, "图片验证码错误");
        }
        String newCode = cachedCode.toString();
        // 如果存储的验证码为空，抛出异常
        if(StrUtil.isBlank(newCode)){
            throw new BusinessException(406,"图片验证码错误");
        }
        // 比较用户输入的验证码和存储的验证码是否一致
        if(!code.equals(newCode)){
            throw new BusinessException(406,"图片验证码错误");
        }
        // 验证码正确，返回成功
        return ResultUtils.success(true);
    }

    /**
     * 发送邮箱验证码接口
     * 当用户请求发送邮箱验证码时调用此方法
     *
     * @param emailCode 用户的邮箱地址，用于接收验证码
     * @return BaseResponse<Boolean> 返回一个包含操作结果的响应对象
     *
     * 此方法首先会检查传入的邮箱验证码是否为空，如果为空则抛出异常
     * 然后生成一个随机验证码，并将其发送到用户的邮箱地址
     * 同时，使用Redis来限制验证码发送的尝试次数
     * 最后，返回一个表示操作成功的响应
     */
    @PostMapping("/emailCode")
    public BaseResponse<Boolean> getEmailCode(String emailCode) {
        // 检查邮箱验证码是否为空
        if (StrUtil.isBlank(emailCode)) {
            throw new BusinessException(405, "邮箱验证码不能为空");
        }
        // 生成随机验证码
        String code = StringUtils.RandomNumberFour();

        // 使用提取的函数处理 Redis 尝试次数
        handleRedisAttemptCount(CodeConstant.REDIS_LOCK_KEY + emailCode,CodeConstant.REDIS_LOCK_TIMEOUT * 100 ,1);

        // 构建邮件内容
        String Value = "<div style=\"background-color: #f0f0f0; padding: 20px;\">\n" +
                "    <h1 style=\"color: #800000;\">星轨向你报到</h1>\n" +
                "    <p style=\"color: #800000;\">该验证码用于注册账号或者修改密码，有效期为5分钟。</p>\n" +
                "    <p style=\"color: #800000;\">请勿泄露和转发此验证码，以保障您的账号安全。</p>\n" +
                "    <p style=\"color: #800000;\">如非您本人操作，请忽略此邮件。</p>\n" +
                "    <p style=\"color: #800000;\">您本次的验证码为：<span style=\"color: black; font-weight: bold;\">" + code + "</span></p>\n" +
                "</div>";
        // 发送邮箱验证码
        sendEmailCode(emailCode, Value);

        // 返回操作成功的结果
        return ResultUtils.success(true);
    }


    /**
     * 获取客户端的IP地址信息
     * 该方法通过HTTP请求获取客户端的IP地址，并将其解析为更详细的地址信息
     *
     * @param request HTTP请求对象，用于获取客户端的请求信息
     * @return 返回一个映射，其中包含IP地址解析后的详细信息
     */
    @GetMapping("/getIdAddress")
    public Map<String, String> ipAddress(HttpServletRequest request){
        // 获取客户端的IP地址
        String ip = NetUtils.getIpAddress(request);
        // 将IP地址解析为更详细的地址信息
        Map<String, String> toIpAddress = NetUtils.getToIpAddress(ip);
        // 返回解析后的地址信息
        return toIpAddress;
    }

    /**
     * 处理用户注册请求
     *
     * @param regiSterDto 包含用户注册信息的数据传输对象
     * @param request HTTP请求对象，用于获取请求相关的信息
     * @return 返回一个包含布尔值的BaseResponse对象，表示注册是否成功
     *
     * 此方法接收用户通过POST请求发送的注册信息，包括邮箱、用户名和密码，
     * 并进行基本的参数校验如果注册信息合法，則调用userService的register方法
     * 进行注册操作，并返回注册结果
     */
    @PostMapping("/register")
    public BaseResponse<Boolean> register(@RequestBody RegiSterDto regiSterDto, HttpServletRequest request){
        //获取用户传递过来的信息
        String email = regiSterDto.getEmail();
        String username = regiSterDto.getUsername();
        String password = regiSterDto.getPassword();
        // TODO 如果注册的时候需要邮箱验证码，那么就请打开
        //String emailCode = regiSterDto.getEmailCode();

        // 校验邮箱参数是否为空
        if(StrUtil.isEmpty(email)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱不能为空");
        }
        // 校验用户名参数是否为空
        if(StrUtil.isEmpty(username)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名不能为空");
        }
        // 校验密码参数是否为空
        if(StrUtil.isEmpty(password)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能为空");
        }
        // TODO 如果注册的时候需要邮箱验证码，那么就请打开
        /*if(StrUtil.isEmpty(emailCode)){
            throw new BusinessException(405,"邮箱验证码不能为空");
        }
        Integer code = (Integer) redisUtils.get(CodeConstant.REDIS_LOCK_KEY + email);
        if(code == null || code < 1){
            throw new BusinessException(406,"邮箱验证码错误");
        }*/

        // 调用用户服务的注册方法，传入用户信息和请求对象
        Boolean result = userService.register(email,username,password,request);
        // 返回注册结果
        return ResultUtils.success(result);
    }

    /**
     * 处理登录请求的控制器方法
     *
     * @param loginDto 包含登录信息的DTO，包括用户名和密码
     * @param request HTTP请求对象，用于获取请求信息
     * @return 返回一个包含登录结果的BaseResponse对象
     *
     * 该方法接收用户名和密码作为参数，验证它们是否为空如果为空，则抛出异常
     * 之后，调用userService的login方法进行登录验证，返回登录结果
     */
    @PostMapping("/login")
    public BaseResponse<Boolean> login(@RequestBody LoginDto loginDto, HttpServletRequest request){
        // 获取用户名和密码
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        // 其他登录验证信息，如验证码等，在此省略

        // 验证用户名是否为空
        if(StrUtil.isEmpty(username)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名不能为空");
        }
        // 验证密码是否为空
        if(StrUtil.isEmpty(password)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能为空");
        }
        /*
        // 验证图片验证码的key是否为空
        if(StrUtil.isEmpty(uuid)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"图片验证码的key不能为空");
        }
        // 验证图片验证码是否为空
        if(StrUtil.isEmpty(code)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"图片验证码不能为空");
        }
        // 从Redis中获取验证码并进行比较
        String redisCode = (String) redisUtils.get(CodeConstant.CHECK_CODE_KEY + uuid);
        if(redisCode.equals(code)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"验证码输入错误");
        }
        */
        // 接下来该轮到登录了
        // 调用用户服务的登录方法进行登录验证
        Boolean result = userService.login(username,password,request);
        // 返回登录结果
        return ResultUtils.success(result);
    }


    /**
     * 获取用户信息接口
     * 该接口用于获取当前登录用户的信息，需要用户具有默认角色权限
     *
     * @return 返回用户的详细信息，包括用户名、角色等
     * @throws BusinessException 如果用户未登录或用户信息不存在，则抛出业务异常
     */
    @GetMapping("/getUserInfo")
    @SaCheckRole(UserConstant.DEFAULT_ROLE)
    public BaseResponse<UserVo> getUserInfo(@RequestParam("id") String id){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",id);
        User user = userService.getOne(queryWrapper);
        // 检查用户是否为空，如果为空则抛出业务异常
        if(user == null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户不存在");
        }
        UserVo userVo = BeanUtil.copyProperties(user, UserVo.class);
        // 检查用户是否存在，如果不存在则抛出业务异常
        // 返回成功响应，包含用户信息
        return ResultUtils.success(userVo);
    }

    /**
     * 处理用户登出请求的控制器方法
     * 使用Get请求映射到/logout路径
     * 需要用户具有默认角色权限才能访问
     *
     * @return 返回一个布尔值表示登出是否成功
     * @throws BusinessException 如果用户未登录，则抛出业务异常
     */
    @GetMapping("/logout")
    @SaCheckRole(UserConstant.DEFAULT_ROLE)
    public BaseResponse<Boolean> logout(){
        // 获取当前登录用户的ID
        String loginUserId  =(String) StpUtil.getLoginId();
        // 如果用户ID为空，说明用户未登录，抛出异常
        if(StrUtil.isEmpty(loginUserId)){
            throw new BusinessException(ErrorCode.NO_LOGIN_CODE);
        }
        // 用户已登录，执行登出操作
        StpUtil.logout(loginUserId);
        // 返回成功登出的结果
        return ResultUtils.success(true);
    }


    /**
     * 处理更新密码请求
     * 该方法允许用户通过POST请求更新他们的密码
     * 需要用户提供旧密码、新密码和确认密码，以及邮箱地址
     *
     * @param updatePasswordDto 包含旧密码、新密码、确认密码和邮箱的请求体
     * @return 返回一个BaseResponse对象，包含更新密码操作的结果（成功或失败）
     * @throws BusinessException 如果参数不合法或密码验证失败，抛出此异常
     */
    @PostMapping("/updatePassword")
    @SaCheckRole(UserConstant.DEFAULT_ROLE)
    public BaseResponse<Boolean> updatePassword(@RequestBody UpdatePasswordDto updatePasswordDto){
        // 获取旧密码、新密码、确认密码和邮箱地址
        String oldPassword = updatePasswordDto.getOldPassword();
        String password = updatePasswordDto.getPassword();
        String okPassword = updatePasswordDto.getOkPassword();
        String email = updatePasswordDto.getEmail();
        // 检查旧密码是否为空
        if(oldPassword.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"旧密码不能为空");
        }
        // 检查新密码是否为空
        if(password.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"新密码不能为空");
        }
        // 检查确认密码是否为空
        if(okPassword.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"确认密码不能为空");
        }
        // 检查邮箱是否为空
        if(email.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱号不能为空");
        }
        // 检查新密码和确认密码是否相同
        if(!password.equals(okPassword)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"新密码和旧密码设置不相同");
        }
        if(oldPassword.equals(password)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"新密码和旧密码设置不能相同");
        }
        // 调用用户服务的更新密码方法
        Boolean result = userService.updatePassword(oldPassword,password,email);
        // 返回更新密码的结果
        return ResultUtils.success(result);
    }

    /**
     * 处理更新用户信息的请求
     * 该方法仅允许具有默认角色的用户执行
     *
     * @param updateUserinfoDto 包含用户信息的DTO对象，包括微信码、昵称、电话、性别和用户简介
     * @return 返回一个BaseResponse对象，包含更新操作的结果
     */
    @PostMapping("/updateUserinfo")
    @SaCheckRole(UserConstant.DEFAULT_ROLE)
    public BaseResponse<Boolean> updateUserinfo(@RequestBody UpdateUserinfoDto updateUserinfoDto){
        // 获取当前登录用户的ID
        String loginUserId  =(String) StpUtil.getLoginId();
        // 如果用户ID为空，说明用户未登录，抛出异常
        if(StrUtil.isEmpty(loginUserId)){
            throw new BusinessException(ErrorCode.NO_LOGIN_CODE);
        }
        // 从DTO中提取用户信息
        String wxCode = updateUserinfoDto.getWxCode();
        String nickName = updateUserinfoDto.getNickName();
        String phone = updateUserinfoDto.getPhone();
        Integer gender = updateUserinfoDto.getGender();
        String userProfile = updateUserinfoDto.getUserProfile();
        String avatarUrl = updateUserinfoDto.getAvatarUrl();
        // 调用服务层方法更新用户信息
        Boolean result = userService.updateUserInfo(wxCode,nickName,avatarUrl,phone,gender,userProfile,loginUserId);
        // 返回更新结果
        return ResultUtils.success(result);
    }


    /**
     * 处理用户添加请求的方法
     *
     * @param addUserDto 包含用户信息的DTO，包括用户名、密码、昵称、邮箱、头像和用户角色
     * @return BaseResponse<Boolean> 返回一个包含添加结果的响应对象
     * 只有管理员才能添加用户
     *
     * 该方法首先从AddUserDto对象中提取用户信息，然后进行参数有效性检查，
     * 如果任何参数为空，则抛出相应的业务异常如果所有参数都有效，它将调用
     * 用户服务层的addUser方法来添加新用户，并返回添加结果
     */
    @PostMapping("/add")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> add(@RequestBody AddUserDto addUserDto){
        // 调用用户服务层的注册方法，传入用户对象
        String username = addUserDto.getUsername();
        String password = addUserDto.getPassword();
        String nickName = addUserDto.getNickName();
        String email = addUserDto.getEmail();
        String avatarUrl = addUserDto.getAvatarUrl();
        String userRole = addUserDto.getUserRole();
        String address = addUserDto.getAddress();
        String phone = addUserDto.getPhone();
        String wxCode = addUserDto.getWxCode();
        // 参数有效性检查
        if(username.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名不能为空");
        }
        if(password.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"密码不能为空");
        }
        if(email.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱号不能为空");
        }
        if(avatarUrl.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"头像不能为空");
        }
        if(userRole.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户权限不能为空");
        }
        if(nickName.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户名不能为空");
        }

        // 调用用户服务层的添加方法
        Boolean result = userService.addUser(username,password,nickName,email,avatarUrl,userRole,address,phone,wxCode);
        //返回注册结果
        return ResultUtils.success(result);
    }

    /**
     * 处理用户移除请求的控制器方法
     * 该方法使用POST请求映射，并要求用户具有管理员角色权限
     *
     * @param removeUserDto 包含待移除用户ID的请求体
     * @return 返回一个布尔值，表示用户是否成功被移除
     * @throws BusinessException 如果用户ID为空，则抛出业务异常
     */
    @PostMapping("/remove")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> removeUser(@RequestBody RemoveUserDto removeUserDto){
        // 获取待移除用户的ID
        String userId = removeUserDto.getUserId();
        // 检查用户ID是否为空，如果为空则抛出业务异常
        if(userId.isEmpty()){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"删除用户不能id为空");
        }
        // 调用用户服务的移除方法，传入用户ID，并返回移除结果
        Boolean result = userService.removeUserId(userId);
        // 使用工具类封装并返回移除操作的成功结果
        return ResultUtils.success(result);
    }

    /**
     * 根据用户ID获取用户信息
     * 该方法使用了Spring MVC的@GetMapping注解来映射HTTP GET请求，
     * 并使用了自定义的AuthCheck注解来检查用户是否具有管理员角色
     *
     * @return 返回一个BaseResponse对象，其中包含用户信息（UserInfoAdminVO）
     *         如果用户不存在，将抛出一个BusinessException异常
     */
    @GetMapping("/getAdminUserInfo")
    public BaseResponse<UserInfoAdminVO> getAdminUserInfo(){
        // 获取当前登录用户的ID
        String loginUserId  =(String) StpUtil.getLoginId();
        // 根据用户ID查询用户信息
        User user = userService.getById(loginUserId);
        //检查用户是否存在
        if(user == null ){
            //如果用户不存在，抛出异常
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"此用户并不存在");
        }
        //将用户对象转换为UserInfoAdminVO对象
        UserInfoAdminVO userInfoAdminVO = BeanUtil.copyProperties(user, UserInfoAdminVO.class);
        //返回成功响应，包含用户信息
        return ResultUtils.success(userInfoAdminVO);
    }

    /**
     * 根据用户ID获取用户信息的VO对象
     * 此方法首先验证用户ID的合法性，然后从服务层获取用户信息，
     * 如果用户存在，则将其转换为UserVo对象并返回
     *
     * @param id 用户ID，必须是正整数
     * @return 包含用户信息的BaseResponse对象
     * @throws BusinessException 如果用户ID非法或用户不存在，抛出业务异常
     */
    @GetMapping("/get/vo")
    public BaseResponse<UserVo> getUserInfoVo(long id){
        // 检查用户ID是否合法
        if(id < 0 ){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户id错误");
        }
        // 通过用户ID获取用户信息
        User user = userService.getById(id);
        // 检查用户是否存在
        if(user == null ){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户不存在");
        }
        // 将用户信息转换为UserVo对象
        UserVo userVo = BeanUtil.copyProperties(user, UserVo.class);
        // 返回成功结果
        return ResultUtils.success(userVo);
    }
    /**
     * 处理用户列表的分页查询请求
     * 该接口要求用户必须具有管理员角色才能访问
     *
     * @param userQueryRequest 包含查询参数的请求体，用于指定查询条件和分页信息
     * @return 返回一个包含用户分页查询结果的响应对象
     */
    @PostMapping("/list/page")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    public BaseResponse<Page<User>> listUserByPage(@RequestBody UserQueryRequest userQueryRequest){
        // 提取当前页码和页面大小
        Integer current = userQueryRequest.getCurrent();
        Integer pagesSize = userQueryRequest.getPagesSize();

        // 执行分页查询
        Page<User> page = userService.page(new Page<>(current, pagesSize), userService.getQueryWrapper(userQueryRequest));

        // 返回成功响应，包含查询结果
        return ResultUtils.success(page);
    }

    @PostMapping("/update/user")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    public BaseResponse<Boolean> adminUpdateUser(@RequestBody AdminUpdateUserDto adminUpdateUserDto) {
        String password = adminUpdateUserDto.getPassword();
        String nickName = adminUpdateUserDto.getNickName();
        String email = adminUpdateUserDto.getEmail();
        String avatarUrl = adminUpdateUserDto.getAvatarUrl();
        Integer gender = adminUpdateUserDto.getGender();
        String address = adminUpdateUserDto.getAddress();
        String phone = adminUpdateUserDto.getPhone();
        String wXCode = adminUpdateUserDto.getWxCode();
        String userProfile = adminUpdateUserDto.getUserProfile();
        String userRole = adminUpdateUserDto.getUserRole();
        String id = adminUpdateUserDto.getId();
        if(StrUtil.isEmpty(nickName)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"昵称不能为空");
        }
        if(StrUtil.isEmpty(email)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"邮箱不能为空");
        }
        if(StrUtil.isEmpty(userRole)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户角色不能为空");
        }
        if(StrUtil.isEmpty(avatarUrl)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"头像不能为空");
        }
        if(StrUtil.isEmpty(address)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"地址不能为空");
        }
        if(StrUtil.isEmpty(phone)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"电话号码不能为空");
        }
        if(StrUtil.isEmpty(wXCode)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"微信号不能为空");
        }
        Boolean result = userService.adminUpdateUser(id,password,nickName,email,avatarUrl,gender,address,phone,wXCode,userProfile,userRole);
        return ResultUtils.success(result);
    }



    /**
     * 向用户发送电子邮件验证码
     *
     * @param toEmail 接收邮件的用户邮箱地址
     * @param value 邮件正文内容，此处为验证码
     *
     * 此方法负责构造邮件内容并发送给指定的邮箱地址
     * 它使用了Spring框架的JavaMailSender来创建和发送邮件
     * 如果邮件发送失败，将抛出自定义的BusinessException异常
     */
    public void sendEmailCode(String toEmail,String value){
        try {
            // 创建MimeMessage实例
            jakarta.mail.internet.MimeMessage message = javaMailSender.createMimeMessage();
            // 使用MimeMessageHelper来设置邮件的各个部分，true表示支持多部分
            MimeMessageHelper helper = new MimeMessageHelper(message,true);
            // 设置发件人邮箱地址
            helper.setFrom(appConfig.getSendUsername());
            // 设置收件人邮箱地址
            helper.setTo(toEmail);
            // 设置邮件主题
            helper.setSubject("星轨向你发来消息");
            // 设置邮件正文内容
            helper.setText(value);
            // 设置邮件发送日期
            helper.setSentDate(new Date());
            // 发送邮件
            javaMailSender.send(message);
        }  catch (jakarta.mail.MessagingException e) {
            log.error("邮件发送失败");
            throw new BusinessException(407,"邮件发送失败");
        }
    }
    /**
     * 处理Redis中尝试次数的逻辑
     * 如果验证码不存在，则初始化尝试次数为1；如果存在，则尝试次数加1，并检查是否超过最大尝试次数
     *
     * @param key Redis中的键，用于存储尝试次数
     * @return 当前的尝试次数
     * @throws BusinessException 如果尝试次数超过最大值，抛出业务异常
     */
    private Integer handleRedisAttemptCount(String key,Integer TimeOut,Integer count) {
        // 从Redis中获取当前key对应的尝试次数
        Object o = redisUtils.get(key);
        Integer attemptCount = null;
        if (o == null) {
            // 如果没有生成过验证码，初始化尝试次数并设置锁
            redisUtils.setex(key, 1, TimeOut);
            attemptCount = 1; // 返回初始尝试次数
        } else {
            // 如果已经生成过验证码，尝试次数加1
            attemptCount = (Integer) o; // 假设 o 是 Integer 类型
            attemptCount++;
            // 检查是否超过最大尝试次数
            if (attemptCount > count) {
                throw new BusinessException(ErrorCode.BUSY_ERROR, "频繁操作，请稍后再试");
            }
            // 更新尝试次数
            redisUtils.setex(key, attemptCount, TimeOut);
        }
        return attemptCount;
    }

    /**
     * 获取用户统计信息
     * 包括总用户数、今日新增、近三天新增、近一周新增、近一个月新增
     *
     * @return 返回用户统计信息
     */
    @GetMapping("/statistics")
    @SaCheckRole(UserConstant.ADMIN_ROLE)
    public BaseResponse<ListUserCountVo> getUserStatistics() {
        // 获取总用户数
        Long totalUsers = userService.count();
        
        // 获取各时间段新增用户数
        Long todayNewUsers = userMapper.getTodayNewUsers();
        Long threeDaysNewUsers = userMapper.getLastThreeDaysNewUsers();
        Long weekNewUsers = userMapper.getLastWeekNewUsers();
        Long monthNewUsers = userMapper.getLastMonthNewUsers();
        
        // 封装结果
        ListUserCountVo statistics = new ListUserCountVo(
            totalUsers,
            todayNewUsers,
            threeDaysNewUsers,
            weekNewUsers,
            monthNewUsers
        );
        
        return ResultUtils.success(statistics);
    }
}
